package bma.common.langutil.concurrent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import junit.framework.TestCase;
import bma.common.langutil.core.ObjectUtil;

public class ExecutorTC extends TestCase {

	final org.slf4j.Logger log = org.slf4j.LoggerFactory
			.getLogger(ExecutorTC.class);

	public void testPassive_OtherClose() throws Exception {

		ScheduledExecutorService e = Executors.newScheduledThreadPool(1);

		final ExecutorPassive exec = new ExecutorPassive("test");
		exec.start();

		if (true) {
			e.schedule(new Runnable() {

				@Override
				public void run() {
					log.info("shutdown main");
					exec.shutdown();
				}
			}, 5, TimeUnit.SECONDS);
		}

		log.info("runing");
		while (exec.run(0)) {
		}

		exec.awaitTermination(1, TimeUnit.SECONDS);

		log.info("quit");
	}

	public void testPassive_MainClose() throws Exception {

		ScheduledExecutorService e = Executors.newScheduledThreadPool(1);

		final ExecutorPassive exec = new ExecutorPassive("test");
		exec.start();

		if (true) {
			e.scheduleAtFixedRate(new Runnable() {

				@Override
				public void run() {
					log.info("post ~~~");
					exec.execute(new Runnable() {

						@Override
						public void run() {
							log.info("step ~~~~");
						}
					});
				}
			}, 5, 1, TimeUnit.SECONDS);
		}

		log.info("runing");
		for (int i = 0; i < 10; i++) {
			if (!exec.run(1000))
				break;
		}

		exec.shutdown();
		log.info("wait");
		exec.awaitTermination(1, TimeUnit.SECONDS);
		log.info("quit");
	}

	public void testPassive_PostAfterClose() throws Exception {

		final ExecutorPassive exec = new ExecutorPassive("test");
		exec.start();

		log.info("runing");
		exec.shutdown();
		exec.execute(new Runnable() {

			@Override
			public void run() {
				log.info("gogogo");
			}
		});
		log.info("wait");
		exec.awaitTermination(1, TimeUnit.SECONDS);
		log.info("quit");
	}

	protected void runTest(ExecutorService ex, int c, final long wait) {
		for (int i = 0; i < c; i++) {
			ex.execute(new Runnable() {

				@Override
				public void run() {
					System.out.println(Thread.currentThread().getName()
							+ " - hello");
					if (wait > 0) {
						ObjectUtil.waitFor(this, wait);
					}
				}
			});
		}
	}

	public void testBMAThreadPool() throws Exception {
		ExecutorService ex = ExecutorUtil.newThreadPool("test", 3, 10, 1000);
		// runTest(ex, 4);
		// ObjectUtil.waitFor(this, 100);
		runTest(ex, 20, 1);
		ObjectUtil.waitFor(this, 5000);
		System.out.println("shutdown");
		ex.shutdown();
		ObjectUtil.waitFor(this, 60 * 1000);
	}

	public void testAtomicSeq() throws Exception {
		ExecutorService ex = Executors.newFixedThreadPool(10);
		final AtomicSeq seq = new AtomicSeq(100);
		for (int i = 0; i < 1000; i++) {
			ex.execute(new Runnable() {

				@Override
				public void run() {
					int v = seq.next();
					System.out.println(v);
				}
			});
		}
		ObjectUtil.waitFor(this, 10 * 1000);
	}
}
